﻿namespace Busconeitor.Domain.Entities
{
    using System;
    using Utils.HashTable;
    using Utils.SortMethods;

    public class DocumentoEntity : BaseEntity, IComparable, IQuickSortComparable
    {
        #region Atributos

        private string _name;
        private string _location;
        private int _pagesCount;
        private int _maxtf;
        private int _minIndex;
        private string _mFragment;
        private double _relevance;
        private long _size; // en bytes
        //Radio para el fragmento
        public static readonly int IndexOffsetRadius = 14;
        private HashList _hashListTerm;

        #endregion

        #region Constructores

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pIdDocument"></param>
        public DocumentoEntity(int pIdDocument)
        {
            Id = pIdDocument;
        }

        /// <summary>
        /// 
        /// </summary>
        public DocumentoEntity()
        {

        }

        #endregion

        #region Propiedades

        /// <summary>
        /// Nombre del documento.
        /// </summary>
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// Localizacion del documento.
        /// </summary>
        public string Location
        {
            get { return _location; }
            set { _location = value; }
        }

        /// <summary>
        /// Cantidad de paginas.
        /// </summary>
        public int PagesCount
        {
            get { return _pagesCount; }
            set { _pagesCount = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public int MaxTf
        {
            get { return _maxtf; }
            set { _maxtf = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public int MinIndex
        {
            get { return _minIndex; }
            set { _minIndex = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public string Fragment
        {
            get { return _mFragment; }
            set { _mFragment = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public double Relevance
        {
            get { return _relevance; }
            set { _relevance = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public long Size
        {
            get { return _size; }
            set { _size = value; }
        }

        #endregion

        #region Metodos

        /// <summary>
        /// Calcula el TF-IDF del documento.
        /// </summary>
        /// <param name="cant"></param>
        /// <returns></returns>
        public double GetWTrDi(int cant)
        {
            var peso = 0.0;
            _hashListTerm.StartIterator();

            while (_hashListTerm.HasNext())
            {
                var term = (TerminoEntity)_hashListTerm.Next();
                peso += ((double)term.TfDoc / (double)term.TfMax * (double)term.GetIdf(cant));
            }

            _relevance = peso;
            
            return _relevance;
        }

        /// <summary>
        /// Determina el orden que tiene el objeto actual con respecto al objeto recibido por parametro.
        /// </summary>
        /// <param name="o">Objeto con el cual se comparara el orden del objeto actual.</param>
        /// <returns>Un entero que si es menor a cero significa que el objeto actual es menor que el recibido por parametro, 
        /// si es mayor a cero significa que el objeto actual es mayor al recibido por paramtero y son iguales si es cero.</returns>
        public int CompareTo(object o)
        {
            return Id - ((DocumentoEntity)o).Id;
        }

        /**
         * Compara dos objetos teniendo en cuenta el algoritmo de ordenamiento
         * quickSort el cual compara los objetos segun el TFIDF de cada uno.
         *
         * @param x Objeto a comparar con el objeto actual.
         * @return un flotante grande que determina cual de los dos objetos es mas
         * grande segun sus TFIDF.
         */
        public double QuickSortCompare(IQuickSortComparable x)
        {
            return (((DocumentoEntity)x).Relevance - _relevance);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pIdTerm"></param>
        /// <param name="pTf"></param>
        /// <param name="pNr"></param>
        /// <param name="maxTf"></param>
        public void AddTermino(int pIdTerm, int pTf, int pNr, int maxTf)
        {
            if (_hashListTerm == null)
            {
                _hashListTerm = new HashList(20);
            }

            _hashListTerm.Put(new TerminoEntity(pIdTerm, pTf, pNr, maxTf));
        }

        public override int GetHashCode()
        {
            return Id;
        }

        #endregion        
    }
}
